package com.wzb.mybatisplus.bitaction.electrumaction.four;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.util.Arrays;

public class PrivateKeyToWIF {

    /**
     * 将原始私钥（16进制字符串）转换为WIF格式（5开头）
     */
    public static String privateKeyToWIF(String hexPrivateKey, boolean isTestnet) {
        try {
            // 1. 添加版本字节
            // 主网: 0x80, 测试网: 0xEF
            byte versionByte = (byte) (isTestnet ? 0xEF : 0x80);

            // 2. 将16进制字符串转换为字节数组
            byte[] privateKeyBytes = hexStringToByteArray(hexPrivateKey);

            // 3. 构建待编码数据：版本字节 + 私钥 + 压缩标志(这里不加，因为5开头是不压缩的)
            byte[] dataToEncode = new byte[1 + privateKeyBytes.length];
            dataToEncode[0] = versionByte;
            System.arraycopy(privateKeyBytes, 0, dataToEncode, 1, privateKeyBytes.length);

            // 4. 计算校验和（双重SHA256，取前4字节）
            byte[] checksum = calculateChecksum(dataToEncode);

            // 5. 构建最终数据：版本字节 + 私钥 + 校验和
            byte[] finalData = new byte[dataToEncode.length + 4];
            System.arraycopy(dataToEncode, 0, finalData, 0, dataToEncode.length);
            System.arraycopy(checksum, 0, finalData, dataToEncode.length, 4);

            // 6. Base58编码
            return base58Encode(finalData);

        } catch (Exception e) {
            throw new RuntimeException("私钥转换失败: " + e.getMessage(), e);
        }
    }

    /**
     * 计算校验和（双重SHA256，取前4字节）
     */
    private static byte[] calculateChecksum(byte[] data) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            // 第一次SHA256
            byte[] firstHash = digest.digest(data);
            // 第二次SHA256
            byte[] secondHash = digest.digest(firstHash);
            // 取前4字节作为校验和
            return Arrays.copyOfRange(secondHash, 0, 4);
        } catch (Exception e) {
            throw new RuntimeException("计算校验和失败", e);
        }
    }

    /**
     * 16进制字符串转字节数组
     */
    private static byte[] hexStringToByteArray(String s) {
        int len = s.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                    + Character.digit(s.charAt(i+1), 16));
        }
        return data;
    }

    /**
     * Base58编码实现
     */
    private static String base58Encode(byte[] input) {
        BigInteger num = BigInteger.ZERO;
        int leadingZeros = 0;

        // 计算前导0的数量
        for (byte b : input) {
            if (b == 0) {
                leadingZeros++;
            } else {
                break;
            }
        }

        // 将字节数组转换为大整数
        for (int i = 0; i < input.length; i++) {
            num = num.multiply(BigInteger.valueOf(256));
            num = num.add(BigInteger.valueOf(input[i] & 0xFF));
        }

        // Base58字符集
        final String BASE58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";

        // 编码
        StringBuilder result = new StringBuilder();
        while (num.compareTo(BigInteger.ZERO) > 0) {
            BigInteger[] divmod = num.divideAndRemainder(BigInteger.valueOf(58));
            num = divmod[0];
            int remainder = divmod[1].intValue();
            result.insert(0, BASE58.charAt(remainder));
        }

        // 添加前导'1'（对应字节0）
        for (int i = 0; i < leadingZeros; i++) {
            result.insert(0, '1');
        }

        return result.toString();
    }

    /**
     * 验证WIF格式私钥的有效性
     */
    public static boolean validateWIF(String wif) {
        try {
            // Base58解码
            byte[] decoded = base58Decode(wif);

            if (decoded.length < 37) { // 至少 1版本 + 32私钥 + 4校验和
                return false;
            }

            // 提取数据和校验和
            byte[] data = Arrays.copyOfRange(decoded, 0, decoded.length - 4);
            byte[] checksum = Arrays.copyOfRange(decoded, decoded.length - 4, decoded.length);

            // 验证校验和
            byte[] calculatedChecksum = calculateChecksum(data);
            return Arrays.equals(checksum, calculatedChecksum);

        } catch (Exception e) {
            return false;
        }
    }

    /**
     * Base58解码（用于验证）
     */
    private static byte[] base58Decode(String input) {
        final String BASE58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
        BigInteger num = BigInteger.ZERO;

        // 将Base58字符串转换为大整数
        for (int i = 0; i < input.length(); i++) {
            char c = input.charAt(i);
            int digit = BASE58.indexOf(c);
            if (digit == -1) {
                throw new IllegalArgumentException("Invalid Base58 character: " + c);
            }
            num = num.multiply(BigInteger.valueOf(58));
            num = num.add(BigInteger.valueOf(digit));
        }

        // 转换为字节数组
        byte[] bytes = num.toByteArray();

        // 处理前导0
        int leadingZeros = 0;
        for (int i = 0; i < input.length() && input.charAt(i) == '1'; i++) {
            leadingZeros++;
        }

        if (leadingZeros > 0) {
            byte[] tmp = new byte[bytes.length + leadingZeros - (bytes[0] == 0 ? 1 : 0)];
            System.arraycopy(bytes, bytes[0] == 0 ? 1 : 0, tmp, leadingZeros, tmp.length - leadingZeros);
            bytes = tmp;
        }

        return bytes;
    }

    // 测试示例
    public static void main(String[] args) {
        // 示例1：已知的测试私钥
        String hexPrivateKey = "0C28FCA386C7A227600B2FE50B7CAE11EC86D3BF1FBE471BE89827E19D72AA1D";
        String wif = privateKeyToWIF(hexPrivateKey, false); // false表示主网

        System.out.println("原始私钥 (Hex): " + hexPrivateKey);
        System.out.println("WIF 格式 (5开头): " + wif);
        System.out.println("WIF 是否有效: " + validateWIF(wif));

        // 示例2：另一个测试用例
        String hexPrivateKey2 = "E9873D79C6D87DC0FB6A5778633389F4453213303DA61F20BD67FC233AA33262";
        String wif2 = privateKeyToWIF(hexPrivateKey2, false);

        System.out.println("\n原始私钥 (Hex): " + hexPrivateKey2);
        System.out.println("WIF 格式 (5开头): " + wif2);
        System.out.println("WIF 是否有效: " + validateWIF(wif2));
    }
}